using Engine;
using Engine.Graphics;
using Game;
using GameEntitySystem;
using TemplatesDatabase;

namespace SCIENEW {
    public class ComponentHearthFurnaceCastingBasin : ComponentInventoryTankBase, IDrawable, IUpdateable {
        public int ModuleSlotIndex => 0;
        public int ResultSlotIndex => 1;
        public int[] DrawOrders => [0];
        public UpdateOrder UpdateOrder => UpdateOrder.Default;

        public float m_progress;

        public SubsystemTerrain m_subsystemTerrain;
        public ComponentBlockEntity m_componentBlockEntity;
        public PrimitivesRenderer3D m_primitivesRenderer3D = new();
        public DrawBlockEnvironmentData m_drawBlockEnvironmentData = new();

        public override void Load(ValuesDictionary valuesDictionary, IdToEntityMap idToEntityMap) {
            base.Load(valuesDictionary, idToEntityMap);
            m_subsystemTerrain = Project.FindSubsystem<SubsystemTerrain>(true);
            m_componentBlockEntity = Entity.FindComponent<ComponentBlockEntity>(true);

            UpdateTankCapacity();
        }

        public override void AddSlotItems(int slotIndex, int value, int count) {
            base.AddSlotItems(slotIndex, value, count);
            UpdateTankCapacity();
        }

        public override int RemoveSlotItems(int slotIndex, int count) {
            if (slotIndex == ModuleSlotIndex) SetDefaultCapacity();
            return base.RemoveSlotItems(slotIndex, count);
        }

        public override float GetTankCapacity(int tankIndex, int value) {
            if (FluidsManager.GetFluid(value) is MoltenMetalFluid moltenMetalFluid && moltenMetalFluid.GetMaterial() == Materials.Steel && GetSlotCount(ResultSlotIndex) == 0) return base.GetSlotCapacity(tankIndex, value);
            return 0;
        }

        public override int GetSlotCapacity(int slotIndex, int value) {
            if (slotIndex == ModuleSlotIndex) {
                if (Terrain.ExtractContents(value) == BaseItemBlock.Index
                    && ItemsBlockManager.GetItem(value) is ModuleItem moduleItem
                    && ItemsBlockManager.GetItemIdByMaterial(moduleItem.GetResultType(), Materials.Steel) != 0)
                    return 1;
            }
            return 0;
        }

        public void Update(float dt) {
            m_tanks[0].Volume = Math.Clamp(m_tanks[0].Volume, 0, m_tanks[0].Capacity);
            if (MathF.Abs(m_tanks[0].Volume - m_tanks[0].Capacity) < 0.1f) {//到达额定容量
                if (m_progress >= 1) {//铸造完成
                    m_progress = 0;//清空进度
                    m_tanks[0].Volume = 0;//清空容量
                    m_slots[ResultSlotIndex].Value = GetSlotValue(ModuleSlotIndex) != 0 ? ItemsBlockManager.GetItemIdByMaterial(((ModuleItem)ItemsBlockManager.GetItem(GetSlotValue(ModuleSlotIndex))).GetResultType(), Materials.Steel) : NormalBlockManager.GetNBlockIdByMaterial<MetalNBlock>(Materials.Steel);
                    m_slots[ResultSlotIndex].Count = 1;
                }
                else {
                    m_progress = MathUtils.Min(m_progress + dt * 0.25f, 1);
                }
            }
        }

        public void Draw(Camera camera, int drawOrder) {
            if (!DrawingUtils.IsVisible(m_subsystemTerrain, camera, new Vector3(m_componentBlockEntity.Coordinates))) return;

            Point3 position = m_componentBlockEntity.Coordinates;
            DrawingUtils.ModifyEnvironmentData(m_drawBlockEnvironmentData, m_subsystemTerrain, m_componentBlockEntity.Coordinates);

            int blockValue = GetSlotValue(ModuleSlotIndex);
            if (blockValue != 0) {
                Block block = BlocksManager.Blocks[Terrain.ExtractContents(blockValue)];

                Matrix scaleMatrix = Matrix.CreateScale(24 / 32f, 1f, 24 / 32f);
                Matrix matrix = scaleMatrix * Matrix.CreateTranslation(position.X + 0.5f, position.Y + 0.235f, position.Z + 0.5f);
                block.DrawBlock(m_primitivesRenderer3D, blockValue, Color.White, 1, ref matrix, m_drawBlockEnvironmentData);
            }

            //绘制钢水
            if (GetTankVolume(0) > 0) {
                Block moltenSteelBlock = BlocksManager.Blocks[MoltenSteelBlock.Index];
                float relativeVolume = GetTankVolume(0) / GetTankOriginalCapacity(0);
                Matrix scaleMatrix2 = Matrix.CreateScale(28 / 32f, MathUtils.Lerp(0f, 0.25f, relativeVolume), 28 / 32f);
                Matrix matrix2 = scaleMatrix2 * Matrix.CreateTranslation(position.X + 0.5f, position.Y + 0.36f, position.Z + 0.5f);
                moltenSteelBlock.DrawBlock(m_primitivesRenderer3D, moltenSteelBlock.BlockIndex, Color.White, 1, ref matrix2, m_drawBlockEnvironmentData);
            }

            //绘制铁件
            if (GetSlotCount(ResultSlotIndex) > 0) {
                NormalBlock? steelBlock = NormalBlockManager.GetNBlockByMaterial<MetalNBlock>(Materials.Steel);
                Matrix scaleMatrix3 = Matrix.CreateScale(28 / 32f, 0.25f, 28 / 32f);
                Matrix matrix3 = scaleMatrix3 * Matrix.CreateTranslation(position.X + 0.5f, position.Y + 0.36f, position.Z + 0.5f);
                steelBlock?.DrawBlock(m_primitivesRenderer3D, NormalBlockManager.GetNormalBlockID(steelBlock), Color.White, 1, ref matrix3, m_drawBlockEnvironmentData);
            }

            m_primitivesRenderer3D.Flush(camera.ViewProjectionMatrix);
        }

        //没有模具时，默认的容量
        void SetDefaultCapacity() {
            m_tanks[0].Capacity = CastingUtils.GetSteelItemVolume(NormalBlockManager.GetNBlockIdByMaterial<MetalNBlock>(Materials.Steel));
            m_tanks[0].Volume = Math.Clamp(m_tanks[0].Volume, 0, m_tanks[0].Capacity);
        }

        void UpdateTankCapacity() {
            if (GetSlotCount(ModuleSlotIndex) == 0) SetDefaultCapacity();

            int slotValue = GetSlotValue(ModuleSlotIndex);
            if (ItemsBlockManager.GetItem(slotValue) is not ModuleItem moduleItem) return;
            m_tanks[0].Capacity = CastingUtils.GetSteelItemVolume(ItemsBlockManager.GetItemIdByMaterial(moduleItem.GetResultType(), Materials.Steel));
            m_tanks[0].Volume = Math.Clamp(m_tanks[0].Volume, 0, m_tanks[0].Capacity);
        }
    }
}